﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Net;

namespace FinalClient
{
    delegate void print(string message, params Object[] obj);

    class Client
    {
        private const string SEARCH_COMMAND = "search";

        private const string RESERVE_COMMAND = "reserve";

        private const string CANCEL_COMMAND = "cancel";

        private const string EXIT_COMMAND = "exit";

        private const int NUM_OF_ARGUMENTS = 1;

        private const int SERVER_ADDRESS = 0;

        static void Main(string[] args)
        {
            print console = Console.WriteLine;
            bool terminate = false;
            if (args.Length != 1)
            {
                console( "Error. Invalid parameters.");
                console( "Expected: <server address>.");
                return;
            }
            string serverLocation = args[SERVER_ADDRESS];
            console("About to start client.");
            console("Make sure flight search server is up.");
            console("Press any key when ready.");
            Console.ReadLine();
            FlightSearchServiceClient client = null;
            try
            {
                client = new FlightSearchServiceClient(new BasicHttpBinding(),
                                                    new EndpointAddress(new Uri("http://" + serverLocation)));
            }
            catch (Exception e)
            {
                console("Flight search server is down.");
                console(e.Message);
                console("Press any key");
                Console.ReadLine();
                
                return;
            }
            while (!terminate)
            {
                Console.Write(">$ ");
                string command = Console.ReadLine( );
                string[] commandTokens = command.Split( ' ');
                switch (commandTokens[0])
                {                    
                    case SEARCH_COMMAND:
                        {
                            if (commandTokens.Length != 4)
                            {
                                console( "Invalid search command.");
                                console( "Expected format: search <src> <dst> <date>");
                                continue;
                            }
                            string source = commandTokens[1];
                            string destination = commandTokens[2];
                            string date = commandTokens[3];
                            try
                            {
                                Convert.ToDateTime(date);
                            }
                            catch (InvalidCastException e)
                            {
                                console("Incorrect date format. Please, try again.");
                                continue;
                            }
                            
                            try
                            {
                                TicketSellerService.availableFlight flights = client.flightSearch(source, destination, Convert.ToDateTime(date));
                                console("{0} fligts found", flights.Count);
                                foreach (TicketSellerService.flight flight in flights)
                                {
                                    console("{0} {1} {2} {3} seats {4}$", 
                                            flight.vendor, 
                                            flight.flightNumber, 
                                            flight.date.ToString(),
                                            flight.seatsCount,
                                            flight.price);
                                }
                            }
                            catch (Exception e)
                            {
                                if (e.InnerException is WebException)
                                {
                                    HttpWebResponse response = (HttpWebResponse)((WebException)e.InnerException).Response;
                                    if (response != null)
                                    {
                                        console("Get {0} code from server", response.StatusCode);
                                    }
                                    else
                                    {
                                        console("Failed, search server is down.");
                                    }
                                }
                                else
                                {
                                    console(e.Message);
                                }
                            }
                            break;
                        }
                    case RESERVE_COMMAND:
                        {
                            if (commandTokens.Length != 4)
                            {
                                console("Invalid reservation command. Please, try again.");
                                console("Expected: reserve <seller> <fNum> <date>");
                                continue;
                            }
                            string vendor = commandTokens[1];
                            string flightNum = commandTokens[2];
                            string date = commandTokens[3];

                            try
                            {
                            }
                            catch (InvalidCastException e)
                            {
                                console("Incorrect date format. Please, try again.");
                                continue;
                            }
                            try
                            {
                                TicketSellerService.TicketReservation reservation = client.flightReserve(vendor, flightNum, Convert.ToDateTime(date));
                                console( reservation.statusMessage);
                            }
                            catch (Exception e)
                            {
                                if (e.InnerException is WebException)
                                {
                                    HttpWebResponse response = (HttpWebResponse)((WebException)e.InnerException).Response;
                                    if (response != null)
                                    {
                                        console("Get {0} code from server", response.StatusCode);
                                    }
                                    else
                                    {
                                        console("Failed, search server is down.");
                                    }
                                }
                                else
                                {
                                    console(e.Message);
                                }
                            }
                            break;
                        }
                    case CANCEL_COMMAND:
                        {
                            if (commandTokens.Length != 3)
                            {
                                console("Invalid cancel command. Please, try again.");
                                console("Expected: cancel <seller> <reservationID>");
                                continue;
                            }
                            try
                            {
                                console(client.reservationCancel( commandTokens[1], commandTokens[2]));
                            }
                            catch (Exception e)
                            {
                                if (e.InnerException is WebException)
                                {
                                    HttpWebResponse response = (HttpWebResponse)((WebException)e.InnerException).Response;
                                    if (response != null)
                                    {
                                        console("Get {0} code from server", response.StatusCode);
                                    }
                                    else
                                    {
                                        console("Failed, search server is down.");
                                    }
                                }
                                else
                                {
                                    console(e.Message);
                                }
                            }
                            break;
                        }
                    case EXIT_COMMAND:
                        {
                            terminate = true;
                            break;
                        }
                    default:
                        {
                            console("Invalid command request, try again.");
                            continue;
                        }
                }
            }
        }
    }
}
